﻿using System;
using System.Text.RegularExpressions;
using Krile.Kernel.Data;
using Krile.Common;

namespace Krile.Data
{
    public static class ComparisonExtender
    {
        public static bool Contains(this string original, string value, StringComparison comparisionType)
        {
            if (original == null)
                return value == null;
            else if (value == null)
                return false;
            return original.IndexOf(value, comparisionType) >= 0;
        }
    }

    public class AllSearchData : DefaultSearchDataBase
    {
        public AllSearchData() : base() { }

        public AllSearchData(string arg)
            : base()
        {
            this.Arguments = arg;
            this.SearchType = SearchTypes.Contains;
        }

        public override string Description
        {
            get { return String.Format(Lang.DSData.All_Desc, Arguments) + "(" + GetCurrentSearchTypeName() + ")"; }
        }

        public override string Identification
        {
            get { return "__a4225ab508688ab9d5cc2a1ca2645a3e_KRILE_GENERAL_DEFAULT_ALL"; }
        }

        protected override bool IsMatchedInner(Status status)
        {
            return
                IsSearchDataMatched(status.Text.Original) ||
                IsSearchDataMatched(status.User.Id) ||
                IsSearchDataMatched(status.User.Name) ||
                IsSearchDataMatched(status.ParentService.Name) ||
                (status.StatusPage != null && IsSearchDataMatched(status.StatusPage.OriginalString)) ||
                (
                    status.ReplyData != null && (
                        IsSearchDataMatched(status.ReplyData.ReplyToUserId) ||
                        IsSearchDataMatched(status.ReplyData.ReplyToUserName) ||
                        IsSearchDataMatched(status.ReplyData.ReplyToText)
                    )
                );
        }

        public override string Name
        {
            get { return Lang.DSData.All_Name; }
        }

        public override object Clone()
        {
            var newsd = new AllSearchData();
            newsd.Arguments = this.Arguments;
            newsd.Exclude = this.Exclude;
            newsd.SearchType = this.SearchType;
            return newsd;
        }

        public override string Class
        {
            get { return "General"; }
        }
    }

    public class TextSearchData : DefaultSearchDataBase
    {
        public TextSearchData() : base() { }

        public TextSearchData(string arg)
            : base()
        {
            this.Arguments = arg;
            this.SearchType = SearchTypes.Contains;
            this.Exclude = false;
            this.IgnoreCase = true;
        }

        public override string Description
        {
            get { return String.Format(Lang.DSData.Text_Desc, Arguments) + "(" + GetCurrentSearchTypeName() + ")"; }
        }

        public override string Identification
        {
            get { return "__a4225ab508688ab9d5cc2a1ca2645a3e_KRILE_GENERAL_DEFAULT_TEXT"; }
        }

        protected override bool IsMatchedInner(Status status)
        {
            return IsSearchDataMatched(status.Text.Original);
        }

        public override string Name
        {
            get { return Lang.DSData.Text_Name; }
        }

        public override object Clone()
        {
            var newsd = new TextSearchData();
            newsd.Arguments = this.Arguments;
            newsd.Exclude = this.Exclude;
            newsd.SearchType = this.SearchType;
            return newsd;
        }

        public override string Class
        {
            get { return "Text"; }
        }
    }

    public class UserInfoSearchData : DefaultSearchDataBase
    {
        public UserInfoSearchData() : base() { }

        public UserInfoSearchData(string arg)
            : base()
        {
            this.Arguments = arg;
            this.SearchType = SearchTypes.Contains;
            this.Exclude = false;
            this.IgnoreCase = true;
        }

        public override string Description
        {
            get { return String.Format(Lang.DSData.UserInfo_Desc, Arguments) + "(" + GetCurrentSearchTypeName() + ")"; }
        }

        public override string Identification
        {
            get { return "__a4225ab508688ab9d5cc2a1ca2645a3e_KRILE_GENERAL_DEFAULT_USERINFO"; }
        }

        protected override bool IsMatchedInner(Status status)
        {
            return IsSearchDataMatched(status.User.Name) || IsSearchDataMatched(status.User.Id);
        }

        public override string Name
        {
            get { return Lang.DSData.UserInfo_Name; }
        }

        public override object Clone()
        {
            var newsd = new UserInfoSearchData();
            newsd.Arguments = this.Arguments;
            newsd.Exclude = this.Exclude;
            newsd.SearchType = this.SearchType;
            return newsd;
        }

        public override string Class
        {
            get { return "UserInfo"; }
        }
    }

    public class UserSearchData : DefaultSearchDataBase
    {
        public UserSearchData() : base() { }

        public UserSearchData(string arg)
            : base()
        {
            this.Arguments = arg;
            this.SearchType = SearchTypes.Contains;
            this.Exclude = false;
            this.IgnoreCase = true;
        }

        public override string Description
        {
            get { return String.Format(Lang.DSData.User_Desc, Arguments) + "(" + GetCurrentSearchTypeName() + ")"; }
        }

        public override string Identification
        {
            get { return "__a4225ab508688ab9d5cc2a1ca2645a3e_KRILE_GENERAL_DEFAULT_USER"; }
        }

        protected override bool IsMatchedInner(Status status)
        {
            return IsSearchDataMatched(status.User.Name);
        }

        public override string Name
        {
            get { return Lang.DSData.User_Name; }
        }

        public override object Clone()
        {
            var newsd = new UserSearchData();
            newsd.Arguments = this.Arguments;
            newsd.Exclude = this.Exclude;
            newsd.SearchType = this.SearchType;
            return newsd;
        }

        public override string Class
        {
            get { return "User"; }
        }
    }

    public class UserIdSearchData : DefaultSearchDataBase
    {

        public UserIdSearchData() : base() { }

        public UserIdSearchData(string arg)
            : base()
        {
            this.Arguments = arg;
            this.SearchType = SearchTypes.Equals;
            this.Exclude = false;
            this.IgnoreCase = true;
        }

        public override string Description
        {
            get { return String.Format(Lang.DSData.UId_Desc, Arguments) + "(" + GetCurrentSearchTypeName() + ")"; }
        }

        public override string Identification
        {
            get { return "__a4225ab508688ab9d5cc2a1ca2645a3e_KRILE_GENERAL_DEFAULT_USERID"; }
        }

        protected override bool IsMatchedInner(Status status)
        {
            return IsSearchDataMatched(status.User.Id);
        }

        public override string Name
        {
            get { return Lang.DSData.UId_Name; }
        }

        public override object Clone()
        {
            var newsd = new UserIdSearchData();
            newsd.Arguments = this.Arguments;
            newsd.Exclude = this.Exclude;
            newsd.SearchType = this.SearchType;
            return newsd;
        }

        public override string Class
        {
            get { return "UserId"; }
        }
    }

    public class ReplyTextSearchData : DefaultSearchDataBase
    {
        public ReplyTextSearchData() : base() { }

        public override string Identification
        {
            get { return "__a4225ab508688ab9d5cc2a1ca2645a3e_KRILE_GENERAL_DEFAULT_REPLY_TEXT"; }
        }

        protected override bool IsMatchedInner(Status status)
        {
            if (status.ReplyData == null)
                return false;
            if (status.ReplyData.ReplyToText != null)
                return IsSearchDataMatched(status.ReplyData.ReplyToText);
            else
                if (status.ReplyData.ReplyToId != null &&
                    status.ParentAgent.Status.ServiceStatusIdExists(status.ReplyData.ReplyToId) &&
                    Core.StatusManager.IdExists(status.ParentAgent.Status.GetUidFromServiceStatusId(status.ReplyData.ReplyToId)))
                {
                    return IsSearchDataMatched(Core.StatusManager.GetStatus(status.ParentAgent.Status.GetUidFromServiceStatusId(status.ReplyData.ReplyToId)).Text.Original);
                }
            return false;
        }

        public override string Description
        {
            get { return String.Format(Lang.DSData.ReplyText_Desc, Arguments) + "(" + GetCurrentSearchTypeName() + ")"; }
        }

        public override string Name
        {
            get { return Lang.DSData.ReplyText_Name; }
        }

        public override object Clone()
        {
            var newsd = new ReplyTextSearchData();
            newsd.Arguments = this.Arguments;
            newsd.Exclude = this.Exclude;
            newsd.SearchType = this.SearchType;
            return newsd;
        }

        public override string Class
        {
            get { return "ReplyText"; }
        }
    }

    public class ReplyIdSearchData : DefaultSearchDataBase
    {
        public ReplyIdSearchData() : base() { }

        public ReplyIdSearchData(string arg)
            : base()
        {
            this.Arguments = arg;
            this.SearchType = SearchTypes.Equals;
            this.Exclude = false;
            this.IgnoreCase = true;
        }

        public override string Identification
        {
            get { return "__a4225ab508688ab9d5cc2a1ca2645a3e_KRILE_GENERAL_DEFAULT_REPLY_ID"; }
        }

        protected override bool IsMatchedInner(Status status)
        {
            if (status.ReplyData != null && status.ReplyData.ReplyToId != null)
                return IsSearchDataMatched(status.ReplyData.ReplyToId);
            else
                return false;
        }

        public override string Description
        {
            get { return String.Format(Lang.DSData.ReplyId_Desc, Arguments) + "(" + GetCurrentSearchTypeName() + ")"; }
        }

        public override string Name
        {
            get { return Lang.DSData.ReplyId_Name; }
        }

        public override object Clone()
        {
            var newsd = new ReplyTextSearchData();
            newsd.Arguments = this.Arguments;
            newsd.Exclude = this.Exclude;
            newsd.SearchType = this.SearchType;
            return newsd;
        }

        public override string Class
        {
            get { return "ReplyToID"; }
        }
    }

    public class ReplyUserSearchData : DefaultSearchDataBase
    {
        public ReplyUserSearchData() : base() { }

        public override string Identification
        {
            get { return "__a4225ab508688ab9d5cc2a1ca2645a3e_KRILE_GENERAL_DEFAULT_REPLY_USER"; }
        }

        protected override bool IsMatchedInner(Status status)
        {
            if (status.ReplyData == null)
                return false;
            if (!String.IsNullOrEmpty(status.ReplyData.ReplyToUserName))
                return IsSearchDataMatched(status.ReplyData.ReplyToUserName);
            else
                if (status.ReplyData.ReplyToId != null &&
                    status.ParentAgent.Status.ServiceStatusIdExists(status.ReplyData.ReplyToId) &&
                    Core.StatusManager.IdExists(status.ParentAgent.Status.GetUidFromServiceStatusId(status.ReplyData.ReplyToId)))
                {
                    return IsSearchDataMatched(Core.StatusManager.GetStatus(status.ParentAgent.Status.GetUidFromServiceStatusId(status.ReplyData.ReplyToId)).User.Name);
                }
            return false;
        }

        public override string Description
        {
            get { return String.Format(Lang.DSData.ReplyUser_Desc, Arguments) + "(" + GetCurrentSearchTypeName() + ")"; }
        }

        public override string Name
        {
            get { return Lang.DSData.ReplyUser_Name; }
        }

        public override object Clone()
        {
            var newsd = new ReplyUserSearchData();
            newsd.Arguments = this.Arguments;
            newsd.Exclude = this.Exclude;
            newsd.SearchType = this.SearchType;
            return newsd;
        }

        public override string Class
        {
            get { return "ReplyToUser"; }
        }
    }

    public class ReplyUserIdSearchData : DefaultSearchDataBase
    {
        public ReplyUserIdSearchData() : base() { }

        public ReplyUserIdSearchData(string arg)
            : base()
        {
            this.Arguments = arg;
            this.SearchType = SearchTypes.Equals;
            this.Exclude = false;
            this.IgnoreCase = true;
        }

        public override string Identification
        {
            get { return "__a4225ab508688ab9d5cc2a1ca2645a3e_KRILE_GENERAL_DEFAULT_REPLY_USERID"; }
        }

        protected override bool IsMatchedInner(Status status)
        {
            if (status.ReplyData == null)
                return false;
            if (!String.IsNullOrEmpty(status.ReplyData.ReplyToUserId))
                return IsSearchDataMatched(status.ReplyData.ReplyToUserId);
            else
                if (status.ReplyData.ReplyToId != null &&
                    status.ParentAgent.Status.ServiceStatusIdExists(status.ReplyData.ReplyToId) &&
                    Core.StatusManager.IdExists(status.ParentAgent.Status.GetUidFromServiceStatusId(status.ReplyData.ReplyToId)))
                {
                    return IsSearchDataMatched(Core.StatusManager.GetStatus(status.ParentAgent.Status.GetUidFromServiceStatusId(status.ReplyData.ReplyToId)).User.Id);
                }
            return false;
        }

        public override string Description
        {
            get { return String.Format(Lang.DSData.ReplyUId_Desc, Arguments) + "(" + GetCurrentSearchTypeName() + ")"; }
        }

        public override string Name
        {
            get { return Lang.DSData.ReplyUId_Name; }
        }

        public override object Clone()
        {
            var newsd = new ReplyUserIdSearchData();
            newsd.Arguments = this.Arguments;
            newsd.Exclude = this.Exclude;
            newsd.SearchType = this.SearchType;
            return newsd;
        }

        public override string Class
        {
            get { return "ReplyToUserID"; }
        }
    }

    public class ServiceIdSearchData : DefaultSearchDataBase
    {
        public ServiceIdSearchData() : base() { }

        public ServiceIdSearchData(string arg)
            : base()
        {
            this.Arguments = arg;
            this.SearchType = SearchTypes.Equals;
            this.Exclude = false;
        }


        public override string Description
        {
            get { return String.Format(Lang.DSData.SvcId_Desc, Arguments) + "(" + GetCurrentSearchTypeName() + ")"; }
        }

        public override string Identification
        {
            get { return "__a4225ab508688ab9d5cc2a1ca2645a3e_KRILE_GENERAL_DEFAULT_SVCID"; }
        }

        protected override bool IsMatchedInner(Status status)
        {
            return IsSearchDataMatched(status.ParentService.Id);
        }

        public override string Name
        {
            get { return Lang.DSData.SvcId_Name; }
        }

        public override object Clone()
        {
            var newsd = new ServiceIdSearchData();
            newsd.Arguments = this.Arguments;
            newsd.Exclude = this.Exclude;
            newsd.SearchType = this.SearchType;
            return newsd;
        }

        public override string Class
        {
            get { return "ServiceID"; }
        }
    }

    public class ServiceSearchData : DefaultSearchDataBase
    {
        public ServiceSearchData() : base() { }

        public ServiceSearchData(string arg)
            : base()
        {
            this.Arguments = arg;
            this.SearchType = SearchTypes.Equals;
            this.Exclude = false;
        }


        public override string Description
        {
            get { return String.Format(Lang.DSData.Svc_Desc, Arguments) + "(" + GetCurrentSearchTypeName() + ")"; }
        }

        public override string Identification
        {
            get { return "__a4225ab508688ab9d5cc2a1ca2645a3e_KRILE_GENERAL_DEFAULT_SVC"; }
        }

        protected override bool IsMatchedInner(Status status)
        {
            return IsSearchDataMatched(status.ParentService.Name);
        }

        public override string Name
        {
            get { return Lang.DSData.Svc_Name; }
        }

        public override object Clone()
        {
            var newsd = new ServiceIdSearchData();
            newsd.Arguments = this.Arguments;
            newsd.Exclude = this.Exclude;
            newsd.SearchType = this.SearchType;
            return newsd;
        }

        public override string Class
        {
            get { return "Service"; }
        }
    }

    public class UIDSearchData : SingleSearchData
    {
        public override string Identification
        {
            get { return "KRILE_INTERNAL_UID_SEARCH"; }
        }

        public ulong UID { get; set; }

        protected override bool IsMatchedInner(Status status)
        {
            return status.UID == UID;
        }

        public override string Description
        {
            get { return "Search with Krile internal UID"; }
        }

        public override string Name
        {
            get {  return "Krile internal UID search"; }
        }

        public override object Clone()
        {
            return new UIDSearchData() { Exclude = Exclude, UID = UID };
        }

        public override void AcceptArgument(object[] arguments)
        {
            AssertTypeof(arguments, typeof(long));
            this.UID = (ulong)arguments[0];
        }

        public override string Method
        {
            get { return "UniversalID"; }
        }

        public override string Class
        {
            get { return "System"; }
        }

        protected override string WriteArguments()
        {
            return this.UID.ToString();
        }
    }

    public class FollowingSearchData : NoneSearchData
    {
        public override string Identification
        {
            get { return "KRILE_USER_FOLLOWING"; }
        }

        protected override bool IsMatchedInner(Status status)
        {
            return status.User != null && status.User.Following;
        }

        public override string Description
        {
            get { return Lang.DSData.Following_Desc; }
        }

        public override string Name
        {
            get {return Lang.DSData.Following_Name; }
        }

        public override object Clone()
        {
            return new FollowingSearchData();
        }

        public override string Method
        {
            get { return "IsFollowing"; }
        }

        public override string Class
        {
            get { return "System"; }
        }
    }

    public class MentionsSearchData : NoneSearchData
    {
        public override string Identification
        {
            get { return "KRILE_MENTIONS"; }
        }

        protected override bool IsMatchedInner(Status status)
        {
            return
                status.ReplyData != null &&
                status.ReplyData.ReplyToUserId != null &&
                status.ParentAgent.IsMasterId(status.ReplyData.ReplyToUserId);
        }

        public override string Description
        {
            get { return Lang.DSData.Mentions_Desc; }
        }

        public override string Name
        {
            get { return Lang.DSData.Mentions_Name; }
        }

        public override object Clone()
        {
            return new MentionsSearchData();
        }

        public override string Method
        {
            get { return "IsMentions"; }
        }

        public override string Class
        {
            get { return "System"; }
        }
    }

    public class FavoredSearchData : NoneSearchData
    {

        public override string Identification
        {
            get { return "KRILE_FAVORED"; }
        }

        protected override bool IsMatchedInner(Status status)
        {
            return status.Favored;
        }

        public override string Description
        {
            get { return Lang.DSData.Favored_Desc; }
        }

        public override string Name
        {
            get { return Lang.DSData.Favored_Name; }
        }

        public override object Clone()
        {
            return new FavoredSearchData();
        }

        public override string Method
        {
            get { return "IsFavored"; }
        }

        public override string Class
        {
            get { return "System"; }
        }
    }

}